// 缓存策略工具
import { ref, computed } from 'vue'

// 缓存配置接口
interface CacheConfig {
  strategy: 'cache-first' | 'network-first' | 'stale-while-revalidate' | 'network-only' | 'cache-only'
  maxAge: number // 毫秒
  maxEntries?: number
  updateOn?: 'load' | 'idle' | 'interval'
  compression?: boolean
}

// 缓存项接口
interface CacheItem<T = any> {
  data: T
  timestamp: number
  etag?: string
  expires?: number
  size: number
  hits: number
}

// 智能缓存管理器
export class SmartCacheManager {
  private cache = new Map<string, CacheItem>()
  private storage: Storage
  private config: CacheConfig
  private maxMemorySize = 50 * 1024 * 1024 // 50MB
  private currentMemorySize = 0

  constructor(config: CacheConfig, useSessionStorage = false) {
    this.config = config
    this.storage = useSessionStorage ? sessionStorage : localStorage
    this.loadFromStorage()
    this.setupCleanup()
  }

  // 获取缓存数据
  async get<T>(key: string): Promise<T | null> {
    const cacheItem = this.cache.get(key)
    
    if (!cacheItem) {
      return null
    }

    // 检查是否过期
    if (this.isExpired(cacheItem)) {
      this.delete(key)
      return null
    }

    // 更新访问次数
    cacheItem.hits++
    
    // 根据策略处理缓存
    switch (this.config.strategy) {
      case 'cache-first':
        return cacheItem.data
      
      case 'stale-while-revalidate':
        // 返回缓存数据，但在后台更新
        this.revalidateInBackground(key)
        return cacheItem.data
      
      case 'network-first':
        // 优先网络，降级到缓存
        try {
          const networkData = await this.fetchFromNetwork(key)
          if (networkData) {
            this.set(key, networkData)
            return networkData
          }
        } catch (error) {
          console.warn(`网络获取失败，使用缓存: ${key}`, error)
        }
        return cacheItem.data
      
      default:
        return cacheItem.data
    }
  }

  // 设置缓存数据
  set<T>(key: string, data: T, customMaxAge?: number): void {
    const size = this.calculateSize(data)
    const maxAge = customMaxAge || this.config.maxAge
    
    // 检查内存限制
    if (this.currentMemorySize + size > this.maxMemorySize) {
      this.evictLRU(size)
    }

    const cacheItem: CacheItem<T> = {
      data,
      timestamp: Date.now(),
      expires: Date.now() + maxAge,
      size,
      hits: 0
    }

    // 如果是更新现有项，先减去旧的大小
    const existingItem = this.cache.get(key)
    if (existingItem) {
      this.currentMemorySize -= existingItem.size
    }

    this.cache.set(key, cacheItem)
    this.currentMemorySize += size
    
    // 持久化到存储
    this.saveToStorage(key, cacheItem)
  }

  // 删除缓存项
  delete(key: string): boolean {
    const cacheItem = this.cache.get(key)
    if (cacheItem) {
      this.currentMemorySize -= cacheItem.size
      this.cache.delete(key)
      this.removeFromStorage(key)
      return true
    }
    return false
  }

  // 清空所有缓存
  clear(): void {
    this.cache.clear()
    this.currentMemorySize = 0
    this.clearStorage()
  }

  // 检查是否过期
  private isExpired(item: CacheItem): boolean {
    if (!item.expires) return false
    return Date.now() > item.expires
  }

  // 计算数据大小（简化版）
  private calculateSize(data: any): number {
    const json = JSON.stringify(data)
    return new Blob([json]).size
  }

  // LRU 淘汰策略
  private evictLRU(neededSize: number): void {
    const items = Array.from(this.cache.entries())
    
    // 按访问次数和时间排序
    items.sort(([, a], [, b]) => {
      const aScore = a.hits / (Date.now() - a.timestamp)
      const bScore = b.hits / (Date.now() - b.timestamp)
      return aScore - bScore
    })

    let freedSize = 0
    for (const [key, item] of items) {
      if (freedSize >= neededSize) break
      
      this.delete(key)
      freedSize += item.size
    }
  }

  // 后台重新验证
  private async revalidateInBackground(key: string): Promise<void> {
    try {
      const freshData = await this.fetchFromNetwork(key)
      if (freshData) {
        this.set(key, freshData)
      }
    } catch (error) {
      console.warn(`后台重新验证失败: ${key}`, error)
    }
  }

  // 从网络获取数据（需要具体实现）
  private async fetchFromNetwork(key: string): Promise<any> {
    // 这里需要根据具体的API接口实现
    throw new Error('fetchFromNetwork 需要具体实现')
  }

  // 持久化相关方法
  private loadFromStorage(): void {
    try {
      const keys = Object.keys(this.storage).filter(key => key.startsWith('cache:'))
      
      for (const storageKey of keys) {
        const key = storageKey.replace('cache:', '')
        const itemJson = this.storage.getItem(storageKey)
        
        if (itemJson) {
          const item = JSON.parse(itemJson) as CacheItem
          if (!this.isExpired(item)) {
            this.cache.set(key, item)
            this.currentMemorySize += item.size
          } else {
            this.storage.removeItem(storageKey)
          }
        }
      }
    } catch (error) {
      console.warn('从存储加载缓存失败:', error)
    }
  }

  private saveToStorage(key: string, item: CacheItem): void {
    try {
      this.storage.setItem(`cache:${key}`, JSON.stringify(item))
    } catch (error) {
      console.warn('保存缓存到存储失败:', error)
      // 存储空间不足时，清理旧缓存
      this.evictLRU(item.size)
    }
  }

  private removeFromStorage(key: string): void {
    try {
      this.storage.removeItem(`cache:${key}`)
    } catch (error) {
      console.warn('从存储删除缓存失败:', error)
    }
  }

  private clearStorage(): void {
    try {
      const keys = Object.keys(this.storage).filter(key => key.startsWith('cache:'))
      keys.forEach(key => this.storage.removeItem(key))
    } catch (error) {
      console.warn('清空存储缓存失败:', error)
    }
  }

  // 设置清理任务
  private setupCleanup(): void {
    // 定期清理过期缓存
    setInterval(() => {
      this.cleanupExpiredItems()
    }, 5 * 60 * 1000) // 每5分钟清理一次

    // 页面隐藏时清理
    document.addEventListener('visibilitychange', () => {
      if (document.hidden) {
        this.cleanupExpiredItems()
      }
    })
  }

  private cleanupExpiredItems(): void {
    const expiredKeys: string[] = []
    
    for (const [key, item] of this.cache.entries()) {
      if (this.isExpired(item)) {
        expiredKeys.push(key)
      }
    }

    expiredKeys.forEach(key => this.delete(key))
    
    if (expiredKeys.length > 0) {
      console.log(`清理了 ${expiredKeys.length} 个过期缓存项`)
    }
  }

  // 获取缓存统计信息
  getStats() {
    return {
      totalItems: this.cache.size,
      memoryUsage: this.currentMemorySize,
      memoryUsagePercentage: (this.currentMemorySize / this.maxMemorySize) * 100,
      avgHits: Array.from(this.cache.values()).reduce((sum, item) => sum + item.hits, 0) / this.cache.size || 0
    }
  }
}

// HTTP 缓存工具
export class HTTPCacheManager {
  private static instance: HTTPCacheManager
  private interceptors = new Map<string, Function>()

  static getInstance(): HTTPCacheManager {
    if (!HTTPCacheManager.instance) {
      HTTPCacheManager.instance = new HTTPCacheManager()
    }
    return HTTPCacheManager.instance
  }

  // 设置 HTTP 缓存头
  setHTTPCacheHeaders(response: Response, maxAge: number): Response {
    const headers = new Headers(response.headers)
    
    headers.set('Cache-Control', `public, max-age=${maxAge}`)
    headers.set('ETag', this.generateETag(response))
    headers.set('Last-Modified', new Date().toUTCString())
    
    return new Response(response.body, {
      status: response.status,
      statusText: response.statusText,
      headers
    })
  }

  // 生成 ETag
  private generateETag(response: Response): string {
    // 简化版本，实际应用中应该基于内容生成
    return `"${Date.now()}-${Math.random().toString(36).substr(2, 9)}"`
  }

  // 检查缓存有效性
  async checkCacheValidity(url: string, cachedETag?: string): Promise<boolean> {
    try {
      const response = await fetch(url, {
        method: 'HEAD',
        headers: cachedETag ? { 'If-None-Match': cachedETag } : {}
      })
      
      return response.status === 304 // Not Modified
    } catch (error) {
      console.warn('检查缓存有效性失败:', error)
      return false
    }
  }
}

// Service Worker 缓存集成
export class ServiceWorkerCacheManager {
  private isSupported = 'serviceWorker' in navigator
  private swRegistration: ServiceWorkerRegistration | null = null

  constructor() {
    this.initialize()
  }

  private async initialize(): Promise<void> {
    if (!this.isSupported) {
      console.warn('Service Worker 不受支持')
      return
    }

    try {
      this.swRegistration = await navigator.serviceWorker.ready
      this.setupMessageHandling()
    } catch (error) {
      console.error('Service Worker 初始化失败:', error)
    }
  }

  // 向 Service Worker 发送消息
  private async sendMessage(type: string, data: any): Promise<any> {
    if (!this.swRegistration?.active) {
      throw new Error('Service Worker 未激活')
    }

    return new Promise((resolve, reject) => {
      const messageChannel = new MessageChannel()
      
      messageChannel.port1.onmessage = (event) => {
        if (event.data.error) {
          reject(new Error(event.data.error))
        } else {
          resolve(event.data.result)
        }
      }

      this.swRegistration!.active!.postMessage({
        type,
        data
      }, [messageChannel.port2])
    })
  }

  // 设置消息处理
  private setupMessageHandling(): void {
    navigator.serviceWorker.addEventListener('message', (event) => {
      const { type, data } = event.data
      
      switch (type) {
        case 'CACHE_UPDATED':
          console.log('缓存已更新:', data)
          // 可以在这里触发 UI 更新
          break
        case 'CACHE_ERROR':
          console.error('缓存操作失败:', data)
          break
      }
    })
  }

  // 预缓存资源
  async precacheResources(urls: string[]): Promise<void> {
    try {
      await this.sendMessage('PRECACHE_RESOURCES', { urls })
      console.log('预缓存资源成功:', urls)
    } catch (error) {
      console.error('预缓存资源失败:', error)
    }
  }

  // 清理缓存
  async clearCache(cacheName?: string): Promise<void> {
    try {
      await this.sendMessage('CLEAR_CACHE', { cacheName })
      console.log('缓存清理成功')
    } catch (error) {
      console.error('缓存清理失败:', error)
    }
  }

  // 获取缓存大小
  async getCacheSize(): Promise<number> {
    try {
      const result = await this.sendMessage('GET_CACHE_SIZE', {})
      return result.size
    } catch (error) {
      console.error('获取缓存大小失败:', error)
      return 0
    }
  }
}

// 统一缓存管理器
export function useCacheManager(config?: Partial<CacheConfig>) {
  const defaultConfig: CacheConfig = {
    strategy: 'stale-while-revalidate',
    maxAge: 24 * 60 * 60 * 1000, // 24小时
    maxEntries: 100,
    updateOn: 'load',
    compression: true
  }

  const mergedConfig = { ...defaultConfig, ...config }
  const smartCache = new SmartCacheManager(mergedConfig)
  const httpCache = HTTPCacheManager.getInstance()
  const swCache = new ServiceWorkerCacheManager()

  const cacheStats = computed(() => smartCache.getStats())
  const isOnline = ref(navigator.onLine)

  // 监听网络状态
  const handleOnline = () => { isOnline.value = true }
  const handleOffline = () => { isOnline.value = false }
  
  window.addEventListener('online', handleOnline)
  window.addEventListener('offline', handleOffline)

  // 智能缓存获取
  const smartGet = async <T>(key: string, fetcher?: () => Promise<T>): Promise<T | null> => {
    // 先尝试从内存缓存获取
    let data = await smartCache.get<T>(key)
    
    if (data) {
      return data
    }

    // 如果没有缓存且有网络，尝试获取数据
    if (isOnline.value && fetcher) {
      try {
        data = await fetcher()
        if (data) {
          smartCache.set(key, data)
        }
        return data
      } catch (error) {
        console.warn(`获取数据失败: ${key}`, error)
      }
    }

    return null
  }

  // 智能缓存设置
  const smartSet = <T>(key: string, data: T, customMaxAge?: number): void => {
    smartCache.set(key, data, customMaxAge)
  }

  // 清理缓存
  const clearAll = async (): Promise<void> => {
    smartCache.clear()
    await swCache.clearCache()
  }

  return {
    // 缓存操作
    get: smartGet,
    set: smartSet,
    delete: (key: string) => smartCache.delete(key),
    clear: clearAll,
    
    // 统计信息
    stats: cacheStats,
    isOnline,
    
    // 高级功能
    precacheResources: (urls: string[]) => swCache.precacheResources(urls),
    getCacheSize: () => swCache.getCacheSize(),
    
    // 工具方法
    checkValidity: (url: string, etag?: string) => httpCache.checkCacheValidity(url, etag)
  }
} 